using System;
using System.Collections;
using System.Threading;

namespace sforceExplorer
{
	public class dbReplication
	{
		
		private System.Windows.Forms.TreeView tv;
		private System.Windows.Forms.TextBox errorLog;
		private System.Windows.Forms.StatusBarPanel statusPanel;

		public dbReplication(System.Windows.Forms.TreeView treeview, System.Windows.Forms.TextBox errorBox, System.Windows.Forms.StatusBarPanel status)
		{
			tv = treeview;
			errorLog = errorBox;
			statusPanel = status;
		}


		public void doReplicationMonitor() 
		{
			DateTime endTime = DateTime.Now;

			DateTime startTime = endTime.AddMinutes(Convert.ToDouble(Utility.RepConfig.StartTimeOffset));
			DateTime nextCheck = endTime.AddMinutes(Convert.ToInt32(Utility.RepConfig.interval));
			statusPanel.Text = "Next poll: " + nextCheck.ToString();
			while (Thread.CurrentThread.IsAlive)
			{
				for (int i=0;i<Utility.RepConfig.RetrieveObjects.Length;i++) 
				{
					if (Utility.RepConfig.updates)
						CheckForChanges(tv, Utility.RepConfig.RetrieveObjects[i], startTime, endTime);
					if (Utility.RepConfig.deletes)
						CheckForDeletes(tv, Utility.RepConfig.RetrieveObjects[i], startTime, endTime);
				}
				if (nextCheck < DateTime.Now) 
				{
					nextCheck = DateTime.Now;
					startTime = endTime;
					endTime = nextCheck;
				}
				else 
				{

					Thread.Sleep(nextCheck.Subtract(DateTime.Now));
					endTime = nextCheck;
					startTime = endTime.Subtract(new TimeSpan(0, 0, Convert.ToInt32(Utility.RepConfig.interval), 0, 0));
				}
				nextCheck = endTime.AddMinutes(Convert.ToInt32(Utility.RepConfig.interval));
				statusPanel.Text = "Next poll: " + nextCheck.ToString();
			}
		}

		private bool rootNodeExists(String label) 
		{
			foreach (System.Windows.Forms.TreeNode tn in tv.Nodes) 
			{
				if (tn.Text == label) return true;
			}
			return false;
		}

		private System.Windows.Forms.TreeNode getRootNode(String label) 
		{
			foreach (System.Windows.Forms.TreeNode tn in tv.Nodes) 
			{
				if (tn.Text == label) return tn;
			}
			return null;
		}

		private void CheckForChanges(System.Windows.Forms.TreeView tv, ApiBrowserControl.SelectListChangedArguments objectDef, DateTime startTime, DateTime endTime) 
		{
			string table = objectDef.TableName;
			System.Diagnostics.Trace.WriteLine("Checking for updates: " + table);
			sforce.GetUpdatedResult gur = Utility.binding.getUpdated(table, startTime, endTime);
			string fields = Utility.ConvertArrayToString(objectDef.SelectedFields);

			try 
			{
				System.Windows.Forms.TreeNode root;
				if (rootNodeExists(startTime.ToString() + " to " + endTime.ToString())) 
					root = getRootNode(startTime.ToString() + " to " + endTime.ToString());
				else 
				{
					root = new System.Windows.Forms.TreeNode(startTime.ToString() + " to " + endTime.ToString());
					if (tv.InvokeRequired)
						tv.Invoke(new frmMain.AddToTreeViewDelegate(((frmMain)tv.FindForm()).AddTreeNode), new Object[] {root});
					else
						tv.Nodes.Add(root);
				}

				if (gur.ids != null && gur.ids.Length > 0) 
				{
					System.Windows.Forms.TreeNode tn = new System.Windows.Forms.TreeNode(table + "(" + gur.ids.Length + " records)");
					
					if (tv.InvokeRequired)
						tv.Invoke(new frmMain.AddSubNodeToTreeViewDelegate(((frmMain)tv.FindForm()).AddNodeChild), new Object[] {root, tn});
					else
						root.Nodes.Add(tn);
					tn.ForeColor = System.Drawing.Color.Green;
				
					if (gur.ids.Length > 0)
					{
						String[] names = new String[gur.ids.Length];
						ArrayList recs = Utility.ConvertRetrieveResultsToHashtable(Utility.binding.retrieve(fields, table, gur.ids));
						for (int i=0;i<gur.ids.Length;i++) 
						{
							Hashtable record = (Hashtable)recs[i];
							try 
							{
								System.Windows.Forms.TreeNode itemNode = new System.Windows.Forms.TreeNode(gur.ids[i] + " - " + (string)record["Id"]);
								for (int k=0;k<objectDef.SelectedFields.Length;k++) 
								{
									string fieldName = objectDef.SelectedFields[k];
									string fieldVal = "";
									if (record[fieldName.ToLower()].ToString().Equals(String.Empty)) 
										fieldVal = "null";
									else
										fieldVal = (string)record[fieldName.ToLower()].ToString();

									itemNode.Nodes.Add(new System.Windows.Forms.TreeNode(fieldName + " - " + fieldVal));
								}
								itemNode.ForeColor = System.Drawing.Color.Green;
								if (tv.InvokeRequired)
									tv.Invoke(new frmMain.AddSubNodeToTreeViewDelegate(((frmMain)tv.FindForm()).AddNodeChild), new Object[] {tn, itemNode});
								else
									tn.Nodes.Add(itemNode);
							} 
							catch(Exception ex1) 
							{
								if (errorLog.InvokeRequired)
									errorLog.Invoke(new frmMain.AddToErrorLogDelegate(((frmMain)tv.FindForm()).AddErrorLogText), new Object[] {"[" + DateTime.Now.ToString() + "] - " + table + ":" + gur.ids[i] + " ==> " + ex1.Message + System.Environment.NewLine + System.Environment.NewLine});
								else
									errorLog.Text += "[" + DateTime.Now.ToString() + "] - " + table + ":" + gur.ids[i] + " ==> " + ex1.Message + System.Environment.NewLine + System.Environment.NewLine;
							}
						}
					}
					
				}
			}
			catch (Exception ex) 
			{
				if (errorLog.InvokeRequired)
					errorLog.Invoke(new frmMain.AddToErrorLogDelegate(((frmMain)tv.FindForm()).AddErrorLogText), new Object[] {"[" + DateTime.Now.ToString() + "] - " + table + " ==> " + ex.Message + System.Environment.NewLine + System.Environment.NewLine + System.Environment.NewLine + System.Environment.NewLine});
				else
					errorLog.Text += "[" + DateTime.Now.ToString() + "] - " + table + " ==> " + ex.Message + System.Environment.NewLine + System.Environment.NewLine;
			}
		}

		private void CheckForDeletes(System.Windows.Forms.TreeView tv, ApiBrowserControl.SelectListChangedArguments objectDef, DateTime startTime, DateTime endTime) 
		{
			string table = objectDef.TableName;
			System.Diagnostics.Trace.WriteLine("Checking for Deletes: " + table);
			sforce.GetDeletedResult gdr = Utility.binding.getDeleted(table, startTime, endTime);
			
			if (gdr.deletedRecords  != null && gdr.deletedRecords.Length > 0) 
			{
				try 
				{
					System.Windows.Forms.TreeNode root;
					if (rootNodeExists(startTime.ToString() + " to " + endTime.ToString())) 
						root = getRootNode(startTime.ToString() + " to " + endTime.ToString());
					else 
					{
						root = new System.Windows.Forms.TreeNode(startTime.ToString() + " to " + endTime.ToString());
						if (tv.InvokeRequired)
							tv.Invoke(new frmMain.AddToTreeViewDelegate(((frmMain)tv.FindForm()).AddTreeNode), new Object[] {root});
						else
							tv.Nodes.Add(root);
					}

					System.Windows.Forms.TreeNode tn = new System.Windows.Forms.TreeNode(table + "(" + gdr.deletedRecords.Length + " records)");
					
					if (tv.InvokeRequired)
						tv.Invoke(new frmMain.AddSubNodeToTreeViewDelegate(((frmMain)tv.FindForm()).AddNodeChild), new Object[] {root, tn});
					else
						root.Nodes.Add(tn);
					tn.ForeColor = System.Drawing.Color.Red;
				
					if (gdr.deletedRecords.Length > 0)
					{
						for (int i=0;i<gdr.deletedRecords.Length;i++) 
						{
							try 
							{
								System.Windows.Forms.TreeNode itemNode = new System.Windows.Forms.TreeNode(gdr.deletedRecords[i].id + " - " + gdr.deletedRecords[i].deletedDate.ToString());
								itemNode.ForeColor = System.Drawing.Color.Red;
								if (tv.InvokeRequired)
									tv.Invoke(new frmMain.AddSubNodeToTreeViewDelegate(((frmMain)tv.FindForm()).AddNodeChild), new Object[] {tn, itemNode});
								else
									tn.Nodes.Add(itemNode);
							} 
							catch(Exception ex1) 
							{
								if (errorLog.InvokeRequired)
									errorLog.Invoke(new frmMain.AddToErrorLogDelegate(((frmMain)tv.FindForm()).AddErrorLogText), new Object[] {"[" + DateTime.Now.ToString() + "] - " + table + ":" + gdr.deletedRecords[i].id + " ==> " + ex1.Message + System.Environment.NewLine + System.Environment.NewLine});
								else
									errorLog.Text += "[" + DateTime.Now.ToString() + "] - " + table + ":" + gdr.deletedRecords[i].id + " ==> " + ex1.Message + System.Environment.NewLine + System.Environment.NewLine;
							}
						}
					}
					
				} 
				catch (Exception ex) 
				{
					if (errorLog.InvokeRequired)
						errorLog.Invoke(new frmMain.AddToErrorLogDelegate(((frmMain)tv.FindForm()).AddErrorLogText), new Object[] {"[" + DateTime.Now.ToString() + "] - " + table + " ==> " + ex.Message + System.Environment.NewLine + System.Environment.NewLine + System.Environment.NewLine + System.Environment.NewLine});
					else
						errorLog.Text += "[" + DateTime.Now.ToString() + "] - " + table + " ==> " + ex.Message + System.Environment.NewLine + System.Environment.NewLine;
				}
			}
		}
	

	}
}
